import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor
from sklearn.cluster import KMeans, DBSCAN
from sklearn.mixture import GaussianMixture
from sklearn.metrics import mean_squared_error, r2_score, silhouette_score
import matplotlib.pyplot as plt

# 加载数据
data = pd.read_excel(r"C:\pythondata\lasthomework.xlsx")

# 数据预处理
# 对类别特征进行标签编码
label_encoder = LabelEncoder()
data['stock'] = label_encoder.fit_transform(data['stock'])

# 特征选择
features = ['open', 'high', 'low', 'close', 'volume', 'percent_change_price',
            'percent_chagne_volume_over_last_wek', 'previous_weeks_volume',
            'next_weeks_open','next_weeks_close','percent_change_next_weeks_price','following week days_to_next_dividend','percent_return_next_dividend']
target = 'percent_change_next_weeks_price'

X = data[features]
y = data[target]

# 数据标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)

# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

cluster_models = [
    ('KMeans', KMeans(n_clusters=3, random_state=42)),
    ('DBSCAN', DBSCAN(eps=0.5, min_samples=5)),
    ('Gaussian Mixture', GaussianMixture(n_components=3, random_state=42))
]

for name, model in cluster_models:
    model.fit(X)
    if hasattr(model, 'labels_'):
        labels = model.labels_
        unique_labels = np.unique(labels)
        if len(unique_labels) > 1:
            silhouette = silhouette_score(X, labels)
            print(f"{name} Silhouette Score: {silhouette:.2f}")
        else:
            print(f"{name} has only one cluster label, skipping silhouette score calculation.")
    else:
        print(f"{name} does not have a 'labels_' attribute.")

# 可视化聚类结果
plt.figure(figsize=(15, 6))
plt.subplot(1, 3, 1)
model = cluster_models[0][1]
labels = model.labels_
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.title('KMeans Clustering')

plt.subplot(1, 3, 2)
model = cluster_models[1][1]
labels = model.labels_
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.title('DBSCAN Clustering')

plt.subplot(1, 3, 3)
model = cluster_models[2][1]
labels = model.predict(X)
plt.scatter(X[:, 0], X[:, 1], c=labels)
plt.title('Gaussian Mixture Clustering')
plt.show()

# 建模
# 线性回归
linear_model = LinearRegression()
linear_model.fit(X_train, y_train)
linear_pred = linear_model.predict(X_test)
linear_mse = mean_squared_error(y_test, linear_pred)
linear_r2 = r2_score(y_test, linear_pred)
print(f"Linear Regression MSE: {linear_mse:.2f}, R^2: {linear_r2:.2f}")

# 随机森林回归
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
rf_pred = rf_model.predict(X_test)
rf_mse = mean_squared_error(y_test, rf_pred)
rf_r2 = r2_score(y_test, rf_pred)
print(f"Random Forest Regression MSE: {rf_mse:.2f}, R^2: {rf_r2:.2f}")

# 模型验证与应用
# 绘制实际值与预测值对比图
plt.figure(figsize=(10, 6))
# plt.plot(y_test, label='Actual')
plt.plot(linear_pred, label='Linear Regression')
plt.plot(rf_pred, label='Random Forest Regression')
plt.xlabel('Index')
plt.ylabel('Percent Change Next Week Price')
plt.title('Actual vs Predicted Values')
plt.legend()
plt.show()

models = [
    ('Support Vector Regression', SVR(kernel='rbf')), #SVR回归模型
    ('KNN Regression', KNeighborsRegressor())       #KNN回归模型
]

results = []
for name, model in models:
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    mse = mean_squared_error(y_test, pred)
    r2 = r2_score(y_test, pred)
    results.append((name, mse, r2))
    print(f"{name} MSE: {mse:.2f}, R^2: {r2:.2f}")

# 模型验证与应用
# 绘制实际值与预测值对比图
plt.figure(figsize=(10, 6))
for i, (name, _, _) in enumerate(results):
    model = models[i][1]
    pred = model.predict(X_test)
    plt.plot(y_test, label='Actual')
    plt.plot(pred, label=name)
plt.xlabel('Index')
plt.ylabel('Percent Change Next Week Price')
plt.title('Actual vs Predicted Values')
plt.legend()
plt.show()

# 部署和模拟验证
# 假设我们选择随机森林回归模型进行部署
best_model = models[1][1]  # 随机森林回归模型

# 模拟一个新的数据样本
new_data = [[16.71, 16.71, 15.64, 15.97, 242963398, -4.42849, 1.380223028, 239655616,16.19,15.79,-2.47066,19, 0.187852]]
new_data = scaler.transform(new_data)

#预测
prediction = best_model.predict(new_data)
print(f"Predicted percent change for next week: {prediction[0]:.2f}%")

# 输出验证日志
with open("C:\pythondata\log.txt", 'w') as f:
    f.write("Validation Log:\n\n")
    for name, mse, r2 in results:
        f.write(f"{name} MSE: {mse:.2f}, R^2: {r2:.2f}\n")
    f.write(f"\nBest Model: {models[1][0]} (Random Forest Regression)")
    f.write(f"\nPredicted percent change for next week: {prediction[0]:.2f}%")

# 计算每只股票的平均回报率
avg_returns = data.groupby('stock')['percent_change_next_weeks_price'].mean()

# 找到回报率最高的股票
best_stock = avg_returns.idxmax()
best_return = avg_returns.max()

print(f"The stock with the highest return is: {label_encoder.inverse_transform([best_stock])[0]}, with an average return of {best_return:.2f}%")



